//    entity language compiler Copyright (C) 2011 Vincent Belliard

//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation version 3 of the License.

//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.

//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void generate_builtins(FILE *file)
{
fprintf(file, "#include <stdio.h>\n") ;
fprintf(file, "#include <stdlib.h>\n") ;
fprintf(file, "#include <string.h>\n") ;
fprintf(file, "#include <fcntl.h>\n") ;
fprintf(file, "#include <unistd.h>\n") ;
fprintf(file, "#include <typeinfo>\n") ;
fprintf(file, "#include <sys/types.h>\n") ;
fprintf(file, "#include <sys/stat.h>\n") ;
fprintf(file, "#define FALSE 0\n") ;
fprintf(file, "#define TRUE 1\n") ;
fprintf(file, "typedef unsigned T_character ;\n") ;
fprintf(file, "typedef unsigned char T_uint_8 ;\n") ;
fprintf(file, "typedef unsigned short T_uint_16 ;\n") ;
fprintf(file, "typedef unsigned T_uint_32 ;\n") ;
fprintf(file, "typedef unsigned long long T_uint_64 ;\n") ;
fprintf(file, "typedef unsigned T_uint_memory ;\n") ;
fprintf(file, "typedef char T_int_8 ;\n") ;
fprintf(file, "typedef short T_int_16 ;\n") ;
fprintf(file, "typedef int T_int_32 ;\n") ;
fprintf(file, "typedef long long T_int_64 ;\n") ;
fprintf(file, "typedef int T_int_memory ;\n") ;
fprintf(file, "typedef double T_real_64 ;\n") ;
fprintf(file, "class T_string_reference ;\n") ;
fprintf(file, "class T_dynamic_string ;\n") ;
fprintf(file, "class CLASS_Object_class ;\n") ;
fprintf(file, "class T_duplicate ;\n") ;
fprintf(file, "extern T_uint_memory strlen_utf8(const char *data) ;\n") ;
fprintf(file, "template<class T, class H> class LIST\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tT *_first ;\n") ;
fprintf(file, "\tT *_last ;\n") ;
fprintf(file, "\tunsigned _count ;\n") ;
fprintf(file, "\tLIST(void) { _first = NULL ; _last = NULL ; _count = 0 ; } ;\n") ;
fprintf(file, "\tvoid insert(T *new_item)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\t((H *)new_item)[-1]._previous = _last ;\n") ;
fprintf(file, "\t\t((H *)new_item)[-1]._next = NULL ;\n") ;
fprintf(file, "\t\tif (_last == NULL) _first = new_item ; else ((H *)_last)[-1]._next = new_item ;\n") ;
fprintf(file, "\t\t_last = new_item ;\n") ;
fprintf(file, "\t\t_count++ ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\tvoid insert_before(T *new_item, void *_ref)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tT *ref = (T *)_ref ;\n") ;
fprintf(file, "\t\t((H *)new_item)[-1]._next = ref ;\n") ;
fprintf(file, "\t\tif (ref == NULL)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\t((H *)new_item)[-1]._previous = _last ;\n") ;
fprintf(file, "\t\t\t_last = new_item ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\telse\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\t((H *)new_item)[-1]._previous = ((H *)ref)[-1]._previous ;\n") ;
fprintf(file, "\t\t\t((H *)ref)[-1]._previous = new_item ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\tif (((H *)new_item)[-1]._previous == NULL)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\t_first = new_item ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\telse\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\t((H *)(((H *)new_item)[-1]._previous))[-1]._next = new_item ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\t_count++ ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\tvoid insert_after(T *new_item, void *_ref)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tT *ref = (T *)_ref ;\n") ;
fprintf(file, "\t\t((H *)new_item)[-1]._previous = ref ;\n") ;
fprintf(file, "\t\tif (ref == NULL)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\t((H *)new_item)[-1]._next = _first ;\n") ;
fprintf(file, "\t\t\t_first = new_item ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\telse\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\t((H *)new_item)[-1]._next = ((H *)ref)[-1]._next ;\n") ;
fprintf(file, "\t\t\t((H *)ref)[-1]._next = new_item ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\tif (((H *)new_item)[-1]._next == NULL)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\t_last = new_item ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\telse\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\t((H *)(((H *)new_item)[-1]._next))[-1]._previous = new_item ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\t_count++ ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\tvoid remove(T *old_item)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tT *previous = ((H *)old_item)[-1]._previous ;\n") ;
fprintf(file, "\t\tT *next = ((H *)old_item)[-1]._next ;\n") ;
fprintf(file, "\t\tif (previous == NULL) _first = next ;\n") ;
fprintf(file, "\t\telse ((H *)previous)[-1]._next = next ;\n") ;
fprintf(file, "\t\tif (next == NULL) _last = previous ;\n") ;
fprintf(file, "\t\telse ((H *)next)[-1]._previous = previous ;\n") ;
fprintf(file, "\t\t_count-- ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "class T_string_content\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tunsigned links_count ;\n") ;
fprintf(file, "\tunsigned allocated_size ;\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tunsigned size ;\n") ;
fprintf(file, "\tunsigned length ;\n") ;
fprintf(file, "\tchar *data ;\n") ;
fprintf(file, "\tT_string_content(unsigned new_allocated_size, unsigned new_size, unsigned new_length, char *new_data)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tlinks_count = 1 ;\n") ;
fprintf(file, "\t\tallocated_size = new_allocated_size ;\n") ;
fprintf(file, "\t\tsize = new_size ;\n") ;
fprintf(file, "\t\tlength = new_length ;\n") ;
fprintf(file, "\t\tdata = new_data ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t~T_string_content()\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tif (allocated_size > 0) delete data ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\tvoid add_link(void) { links_count++ ; }\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "T_string_content empty_content(0, 0, 0, (char *)\"\") ;\n") ;
fprintf(file, "class T_string\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tT_string_content *content ;\n") ;
fprintf(file, "\tT_string(void) { content = &empty_content ; content->add_link() ; }\n") ;
fprintf(file, "\tT_string(const char *data) { content = new T_string_content(0, strlen(data), strlen_utf8(data), (char *)data) ; }\n") ;
fprintf(file, "\tT_string(char *data, unsigned data_size) { content = new T_string_content(data_size + 1, data_size, strlen_utf8(data), (char *)data) ; }\n") ;
fprintf(file, "\tT_string(const T_string &ref) { content = ref.content ; content->add_link() ; }\n") ;
fprintf(file, "\tT_string(const T_string &start, const T_string_reference &end) ;\n") ;
fprintf(file, "\tT_string(const T_string_reference &start, const T_string_reference &end) ;\n") ;
fprintf(file, "\tconst char *string(void) const { return content->data ; }\n") ;
fprintf(file, "\tvoid set(const char *data) { content = new T_string_content(0, strlen(data), strlen_utf8(data), (char *)data) ; }\n") ;
fprintf(file, "\tvoid set(char *data, unsigned data_size) { content = new T_string_content(data_size + 1, data_size, strlen_utf8(data), (char *)data) ; }\n") ;
fprintf(file, "\tvoid set(const T_string &ref) { ref.content->add_link() ; content = ref.content ; }\n") ;
fprintf(file, "\tvoid set(const T_string &start, const T_string_reference &end) ;\n") ;
fprintf(file, "\tvoid set(const T_string_reference &start, const T_string_reference &end) ;\n") ;
fprintf(file, "\tvoid set(const T_dynamic_string &src) ;\n") ;
fprintf(file, "\tint equals(const T_string &ref) { return strcmp(content->data, ref.content->data) == 0 ; }\n") ;
fprintf(file, "\tT_string &add(const T_string &ref) { unsigned size = content->size + ref.content->size ; char *data = new char[size + 1] ; strcpy(data, content->data) ; strcat(data, ref.content->data) ; return *new T_string(data, size)  ; }\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "class T_dynamic_string\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tunsigned allocated_size ;\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tunsigned size ;\n") ;
fprintf(file, "\tunsigned length ;\n") ;
fprintf(file, "\tchar *data ;\n") ;
fprintf(file, "\tT_dynamic_string(void)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tallocated_size = 1000 ;\n") ;
fprintf(file, "\t\tsize = 0 ;\n") ;
fprintf(file, "\t\tlength = 0 ;\n") ;
fprintf(file, "\t\tdata = new char[1001] ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t~T_dynamic_string()\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tdelete data ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "void add(T_character src)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tint needed = size + 4 - allocated_size ;\n") ;
fprintf(file, "\tif (needed > 0)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tallocated_size += needed + 1000 ;\n") ;
fprintf(file, "\t\tchar *new_data = new char[allocated_size + 1] ;\n") ;
fprintf(file, "\t\tmemcpy(new_data, data, size + 1) ;\n") ;
fprintf(file, "\t\tdelete data ;\n") ;
fprintf(file, "\t\tdata = new_data ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t\tif (src <= 0x7F)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\tdata[size++] = (unsigned char)src ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t\telse if (src <= 0x7FF)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\tdata[size++] = (unsigned char)((src >> 6) | 0xC0) ;\n") ;
fprintf(file, "\t\t\tdata[size++] = (unsigned char)((src & 0x3F) | 0x80) ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t\telse if (src <= 0xFFFF)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\tdata[size++] = (unsigned char)((src >> 12) | 0xE0) ;\n") ;
fprintf(file, "\t\t\tdata[size++] = (unsigned char)((src >> 6) | 0x80) ;\n") ;
fprintf(file, "\t\t\tdata[size++] = (unsigned char)((src & 0x3F) | 0x80) ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t\telse\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\tdata[size++] = (unsigned char)((src >> 18) | 0xF0) ;\n") ;
fprintf(file, "\t\t\tdata[size++] = (unsigned char)((src >> 12) | 0x80) ;\n") ;
fprintf(file, "\t\t\tdata[size++] = (unsigned char)((src >> 6) | 0x80) ;\n") ;
fprintf(file, "\t\t\tdata[size++] = (unsigned char)((src & 0x3F) | 0x80) ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t\tlength++ ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "void add(T_string &src)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tint needed = size + src.content->size - allocated_size ;\n") ;
fprintf(file, "\tif (needed > 0)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tallocated_size += needed + 1000 ;\n") ;
fprintf(file, "\t\tchar *new_data = new char[allocated_size + 1] ;\n") ;
fprintf(file, "\t\tmemcpy(new_data, data, size + 1) ;\n") ;
fprintf(file, "\t\tdelete data ;\n") ;
fprintf(file, "\t\tdata = new_data ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t\tmemcpy(data + size, src.content->data, src.content->size + 1) ;\n") ;
fprintf(file, "\t\tsize += src.content->size ;\n") ;
fprintf(file, "\t\tlength += src.content->length ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "class T_string_reference\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tT_string_content *content ;\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tunsigned offset ;\n") ;
fprintf(file, "\tunsigned utf8_offset ;\n") ;
fprintf(file, "\tT_string_reference(void) { content = &empty_content ; content->add_link() ; offset = 0 ; }\n") ;
fprintf(file, "\tT_string_reference(const T_string &ref) { content = ref.content ; content->add_link() ; offset = 0 ; utf8_offset = 0 ; }\n") ;
fprintf(file, "\tT_string_reference(const T_string_reference &ref) { content = ref.content ; content->add_link() ; offset = ref.offset ; utf8_offset = ref.utf8_offset ; }\n") ;
fprintf(file, "\tT_string_content *get_content(void) const { return content ; }\n") ;
fprintf(file, "\tunsigned current(void) const ;\n") ;
fprintf(file, "\tbool operator==(const T_string_reference &ref) const { return (offset == ref.offset) && (content == ref.content) ; }\n") ;
fprintf(file, "\tvoid set(T_string &ref) { ref.content->add_link() ; content = ref.content ; offset = 0 ; utf8_offset = 0 ; }\n") ;
fprintf(file, "\tvoid set(const T_string_reference &ref) { ref.content->add_link() ; content = ref.content ; offset = ref.offset ; utf8_offset = ref.utf8_offset ; }\n") ;
fprintf(file, "\tvoid increment(void) ;\n") ;
fprintf(file, "\tvoid decrement(void) ;\n") ;
fprintf(file, "\tvoid reset(void) { offset = 0 ; utf8_offset = 0 ; }\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "unsigned strlen_utf8(const char *data)\n") ;
fprintf(file, "{\n") ;
fprintf(file, "unsigned length = 0 ;\n") ;
fprintf(file, "for(;;)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tunsigned loc = *(unsigned char *)data++ ;\n") ;
fprintf(file, "\tif (loc == 0) return length ;\n") ;
fprintf(file, "\tif (loc < 0x80)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tlength++ ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\telse if (loc < 0xE0)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tloc = *(unsigned char *)data ;\n") ;
fprintf(file, "\t\tif (loc == 0) return length ;\n") ;
fprintf(file, "\t\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\tdata++ ;\n") ;
fprintf(file, "\t\t\tlength++ ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\telse if (loc < 0xF0)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tloc = *(unsigned char *)data ;\n") ;
fprintf(file, "\t\tif (loc == 0) return length ;\n") ;
fprintf(file, "\t\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\tdata++ ;\n") ;
fprintf(file, "\t\t\tloc = *(unsigned char *)data ;\n") ;
fprintf(file, "\t\t\tif (loc == 0) return length ;\n") ;
fprintf(file, "\t\t\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t\t\t{\n") ;
fprintf(file, "\t\t\t\tdata++ ;\n") ;
fprintf(file, "\t\t\t\tlength++ ;\n") ;
fprintf(file, "\t\t\t\t}\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\telse if (loc < 0xF8)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tloc = *(unsigned char *)data ;\n") ;
fprintf(file, "\t\tif (loc == 0) return length ;\n") ;
fprintf(file, "\t\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\tdata++ ;\n") ;
fprintf(file, "\t\t\tloc = *(unsigned char *)data ;\n") ;
fprintf(file, "\t\t\tif (loc == 0) return length ;\n") ;
fprintf(file, "\t\t\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t\t\t{\n") ;
fprintf(file, "\t\t\t\tdata++ ;\n") ;
fprintf(file, "\t\t\t\tloc = *(unsigned char *)data ;\n") ;
fprintf(file, "\t\t\t\tif (loc == 0) return length ;\n") ;
fprintf(file, "\t\t\t\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t\t\t\t{\n") ;
fprintf(file, "\t\t\t\t\tdata++ ;\n") ;
fprintf(file, "\t\t\t\t\tlength++ ;\n") ;
fprintf(file, "\t\t\t\t\t}\n") ;
fprintf(file, "\t\t\t\t}\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "}\n") ;
fprintf(file, "T_string::T_string(const T_string_reference &start, const T_string_reference &end)\n") ;
fprintf(file, "{\n") ;
fprintf(file, "T_string_content *loc = start.get_content() ;\n") ;
fprintf(file, "if (end.get_content() != loc)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tcontent = &empty_content ;\n") ;
fprintf(file, "\tcontent->add_link() ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "else\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tunsigned size = end.offset - start.offset ;\n") ;
fprintf(file, "\tchar *buffer = new char[size + 1] ;\n") ;
fprintf(file, "\tmemcpy(buffer, loc->data + start.offset, size) ;\n") ;
fprintf(file, "\tbuffer[size] = 0 ;\n") ;
fprintf(file, "\tcontent = new T_string_content(size, size, end.utf8_offset - start.utf8_offset, buffer) ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "}\n") ;
fprintf(file, "void T_string::set(const T_string_reference &start, const T_string_reference &end)\n") ;
fprintf(file, "{\n") ;
fprintf(file, "T_string_content *loc = start.get_content() ;\n") ;
fprintf(file, "if (end.get_content() != loc)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tcontent = &empty_content ;\n") ;
fprintf(file, "\tcontent->add_link() ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "else\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tunsigned size = end.offset - start.offset ;\n") ;
fprintf(file, "\tchar *buffer = new char[size + 1] ;\n") ;
fprintf(file, "\tmemcpy(buffer, loc->data + start.offset, size) ;\n") ;
fprintf(file, "\tbuffer[size] = 0 ;\n") ;
fprintf(file, "\tcontent = new T_string_content(size, size, end.utf8_offset - start.utf8_offset, buffer) ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "}\n") ;
fprintf(file, "void T_string::set(const T_dynamic_string &src)\n") ;
fprintf(file, "{\n") ;
fprintf(file, "char *buffer = new char[src.size + 1] ;\n") ;
fprintf(file, "memcpy(buffer, src.data, src.size) ;\n") ;
fprintf(file, "buffer[src.size] = 0 ;\n") ;
fprintf(file, "content = new T_string_content(src.size, src.size, src.length, buffer) ;\n") ;
fprintf(file, "}\n") ;
fprintf(file, "unsigned T_string_reference::current(void) const\n") ;
fprintf(file, "{\n") ;
fprintf(file, "const unsigned char *src = (unsigned char *)content->data + offset ;\n") ;
fprintf(file, "unsigned loc = *(unsigned char *)src++ ;\n") ;
fprintf(file, "if (loc < 0x80) return loc ;\n") ;
fprintf(file, "if (loc < 0xE0)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tunsigned result = (loc & 0x1F) << 6 ;\n") ;
fprintf(file, "\tloc = *(unsigned char *)src ;\n") ;
fprintf(file, "\tif ((loc & 0xC0) == 0x80) result |= loc & 0x3F ;\n") ;
fprintf(file, "\treturn result ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "if (loc < 0xF0)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tunsigned result = (loc & 0xF) << 12 ;\n") ;
fprintf(file, "\tloc = *(unsigned char *)src++ ;\n") ;
fprintf(file, "\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tresult |= (loc & 0x3F) << 6 ;\n") ;
fprintf(file, "\t\tloc = *(unsigned char *)src ;\n") ;
fprintf(file, "\t\tif ((loc & 0xC0) == 0x80) result |= loc & 0x3F ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\treturn result ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "if (loc < 0xF8)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tunsigned result = (loc & 0x7) << 18 ;\n") ;
fprintf(file, "\tloc = *(unsigned char *)src++ ;\n") ;
fprintf(file, "\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tresult |= (loc & 0x3F) << 12 ;\n") ;
fprintf(file, "\t\tloc = *(unsigned char *)src++ ;\n") ;
fprintf(file, "\t\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\tresult |= (loc & 0x3F) << 6 ;\n") ;
fprintf(file, "\t\t\tloc = *(unsigned char *)src ;\n") ;
fprintf(file, "\t\t\tif ((loc & 0xC0) == 0x80) result |= loc & 0x3F ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\treturn result ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "return 0 ;\n") ;
fprintf(file, "}\n") ;
fprintf(file, "void T_string_reference::increment(void)\n") ;
fprintf(file, "{\n") ;
fprintf(file, "const unsigned char *src = (unsigned char *)content->data + offset ;\n") ;
fprintf(file, "for(;;)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tunsigned loc = *(unsigned char *)src++ ;\n") ;
fprintf(file, "\tif (loc == 0) return ;\n") ;
fprintf(file, "\toffset++ ;\n") ;
fprintf(file, "\tif (loc < 0x80)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tutf8_offset++ ;\n") ;
fprintf(file, "\t\treturn ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\tif (loc < 0xE0)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tutf8_offset++ ;\n") ;
fprintf(file, "\t\tloc = *(unsigned char *)src ;\n") ;
fprintf(file, "\t\tif ((loc & 0xC0) == 0x80) offset++ ;\n") ;
fprintf(file, "\t\treturn ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\tif (loc < 0xF0)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tutf8_offset++ ;\n") ;
fprintf(file, "\t\tloc = *(unsigned char *)src++ ;\n") ;
fprintf(file, "\t\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\toffset++ ;\n") ;
fprintf(file, "\t\t\tloc = *(unsigned char *)src ;\n") ;
fprintf(file, "\t\t\tif ((loc & 0xC0) == 0x80) offset++ ;\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\treturn ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\tif (loc < 0xF8)\n") ;
fprintf(file, "\t\t{\n") ;
fprintf(file, "\t\tutf8_offset++ ;\n") ;
fprintf(file, "\t\tloc = *(unsigned char *)src++ ;\n") ;
fprintf(file, "\t\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t\t{\n") ;
fprintf(file, "\t\t\toffset++ ;\n") ;
fprintf(file, "\t\t\tloc = *(unsigned char *)src++ ;\n") ;
fprintf(file, "\t\t\tif ((loc & 0xC0) == 0x80)\n") ;
fprintf(file, "\t\t\t\t{\n") ;
fprintf(file, "\t\t\t\toffset++ ;\n") ;
fprintf(file, "\t\t\t\tloc = *(unsigned char *)src ;\n") ;
fprintf(file, "\t\t\t\tif ((loc & 0xC0) == 0x80) offset++ ;\n") ;
fprintf(file, "\t\t\t\t}\n") ;
fprintf(file, "\t\t\t}\n") ;
fprintf(file, "\t\treturn ;\n") ;
fprintf(file, "\t\t}\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "}\n") ;
fprintf(file, "void T_string_reference::decrement(void)\n") ;
fprintf(file, "{\n") ;
fprintf(file, "const unsigned char *src = (unsigned char *)content->data + offset ;\n") ;
fprintf(file, "while (offset > 0)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\toffset-- ;\n") ;
fprintf(file, "\tsrc-- ;\n") ;
fprintf(file, "\tif ((*src < 0x80) || (*src >= 0xC0)) return ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "}\n") ;
fprintf(file, "class T_type_content\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "\tmutable int links_count ;\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tT_type_content(void) { links_count = 1 ; }\n") ;
fprintf(file, "\tvirtual ~T_type_content() {}\n") ;
fprintf(file, "\tvoid add_link(void) const { links_count++ ; }\n") ;
fprintf(file, "\tvirtual void duplicate_field(T_duplicate *duplicate_objects, const char *src, char *dst) const = 0 ;\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "class T_type\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tconst T_type_content *type ;\n") ;
fprintf(file, "\tT_type(void) { type = NULL ; }\n") ;
fprintf(file, "\tT_type(const T_type &ref) { type = ref.type ; if (type != NULL) type->add_link() ; }\n") ;
fprintf(file, "\tT_type(const T_type_content *new_type) { type = new_type ; }\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "class T_type_class : public T_type_content\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tCLASS_Object_class *object_class ;\n") ;
fprintf(file, "\tT_type_class(CLASS_Object_class *new_object_class) { object_class = new_object_class ; }\n") ;
fprintf(file, "\tvirtual ~T_type_class() {} ;\n") ;
fprintf(file, "\tvirtual void duplicate_field(T_duplicate *duplicate_objects, const char *src, char *dst) const ;\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "class T_type_reference : public T_type_content\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tint mode_access ;\n") ;
fprintf(file, "\tT_type type ;\n") ;
fprintf(file, "\tT_type_reference(int new_mode_access, const T_type_content *new_type) : type(new_type) { mode_access = new_mode_access ; }\n") ;
fprintf(file, "\tvirtual ~T_type_reference() {} ;\n") ;
fprintf(file, "\tvirtual void duplicate_field(T_duplicate *duplicate_objects, const char *src, char *dst) const ;\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "class T_type_list : public T_type_content\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tint mode_access ;\n") ;
fprintf(file, "\tT_type type ;\n") ;
fprintf(file, "\tT_type_list(int new_mode_access, const T_type_content *new_type) : type(new_type) { mode_access = new_mode_access ; }\n") ;
fprintf(file, "\tvirtual ~T_type_list() {} ;\n") ;
fprintf(file, "\tvirtual void duplicate_field(T_duplicate *duplicate_objects, const char *src, char *dst) const ;\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "class T_duplicate_object\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tT_duplicate_object *next ;\n") ;
fprintf(file, "\tCLASS_Object_class *old_object ;\n") ;
fprintf(file, "\tCLASS_Object_class *new_object ;\n") ;
fprintf(file, "\tT_duplicate_object(T_duplicate_object *new_next, CLASS_Object_class *new_old_object, CLASS_Object_class *new_new_object) { next = new_next ; old_object = new_old_object ; new_object = new_new_object ; }\n") ;
fprintf(file, "\t} ;\n") ;
fprintf(file, "class T_duplicate\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "public:\n") ;
fprintf(file, "\tT_duplicate_object *first ;\n") ;
fprintf(file, "\tT_duplicate(void) { first = NULL ; }\n") ;
fprintf(file, "\t} ;\n") ;
}

void generate_builtins_code(FILE *file)
{
fprintf(file, "void T_type_class::duplicate_field(T_duplicate *duplicate_objects, const char *src, char *dst) const\n") ;
fprintf(file, "{\n") ;
//fprintf(file, "fprintf(stderr, \"copy %%p -> %%p (%%d)\\n\", src, dst, object_class->_data_size.value) ;\n") ;
fprintf(file, "memcpy(dst, src, object_class->_data_size.value) ;\n") ;
fprintf(file, "}\n") ;
fprintf(file, "void T_type_reference::duplicate_field(T_duplicate *duplicate_objects, const char *src, char *dst) const\n") ;
fprintf(file, "{\n") ;
fprintf(file, "CLASS_Object_class *src_object = *(CLASS_Object_class **)src ;\n") ;
//fprintf(file, "fprintf(stderr, \"duplicate ref (%%d) %%p(%%p) -> %%p\\n\", mode_access, src, src_object, dst) ;\n") ;
fprintf(file, "if (mode_access) *(CLASS_Object_class **)dst = src_object ;\n") ;
fprintf(file, "else if (src_object == NULL) *(CLASS_Object_class **)dst = NULL ;\n") ;
fprintf(file, "else *(CLASS_Object_class **)dst = ___duplicate_object(duplicate_objects, src_object) ;\n") ;
//fprintf(file, "fprintf(stderr, \"=> %%p\\n\", *(CLASS_Object_class **)dst) ;\n") ;
fprintf(file, "}\n") ;
fprintf(file, "void T_type_list::duplicate_field(T_duplicate *duplicate_objects, const char *src, char *dst) const\n") ;
fprintf(file, "{\n") ;
//fprintf(file, "fprintf(stderr, \"duplicate list %%p -> %%p\\n\", src, dst) ;\n") ;
fprintf(file, "LIST<CLASS_Object_class, HEADER_Object_class> *src_list = (LIST<CLASS_Object_class, HEADER_Object_class> *)src ;\n") ;
fprintf(file, "LIST<CLASS_Object_class, HEADER_Object_class> *dst_list = (LIST<CLASS_Object_class, HEADER_Object_class> *)dst ;\n") ;
fprintf(file, "dst_list->_first = NULL ;\n") ;
fprintf(file, "dst_list->_last = NULL ;\n") ;
fprintf(file, "dst_list->_count = 0 ;\n") ;
fprintf(file, "CLASS_Object_class *src_object = src_list->_first ;\n") ;
fprintf(file, "while (src_object != NULL)\n") ;
fprintf(file, "\t{\n") ;
fprintf(file, "dst_list->insert(___duplicate_object(duplicate_objects, src_object)) ;\n") ;
//fprintf(file, "fprintf(stderr, \"list=%%p:%%p,%%p/%%d\\n\", dst_list, dst_list->_first, dst_list->_last, dst_list->_count) ;\n") ;
fprintf(file, "src_object = ((HEADER_Object_class *)src_object)[-1]._next ;\n") ;
fprintf(file, "\t}\n") ;
fprintf(file, "}\n") ;
}
